<template>
  <div>
    <el-dialog
      title="图片裁剪"
      v-model="dialogVisible"
      width="1000px"
      :before-close="handleClose"
      class="rounded-lg"
    >
      <div class="cropper-container">
        <!-- 图片裁剪区域 -->
        <div class="cropper-wrapper">
          <img ref="imageRef" :src="imgSrc" alt="裁剪图片" />
        </div>

        <!-- 预览区域 -->
        <div class="preview-container">
          <!-- <div class="preview-label">预览:</div> -->
          <div class="preview-image">
            <img
              :src="previewSrc"
              alt="预览图片"
              v-if="previewSrc"
              class="rounded"
            />
          </div>
        </div>
      </div>
      <!-- 操作按钮 -->
      <div class="cropper-actions">
        <div>
          <el-button @click="rotateLeft" icon="RefreshLeft">左转</el-button>
          <el-button @click="rotateRight" icon="RefreshRight">右转</el-button>
          <el-button @click="handleReset" icon="Refresh">重置</el-button>
        </div>
        <div>
          <el-button @click="handleClose" icon="CloseBold">取消</el-button>
          <el-button type="primary" @click="handleConfirm" icon="Select"
            >保存</el-button
          >
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, nextTick } from "vue";
import Cropper from "cropperjs";
import "cropperjs/dist/cropper.css";

const props = defineProps({
  modelValue: Boolean,
  imgFile: File,
});

const emit = defineEmits(["update:modelValue", "cropped"]);

const dialogVisible = ref(false);
const imageRef = ref(null);
const cropper = ref(null);
const imgSrc = ref("");
const previewSrc = ref("");

// 固定裁剪比例 (1:1)
const ASPECT_RATIO = 1;
// 固定裁剪尺寸 (300x300)
const CROP_WIDTH = 300;
const CROP_HEIGHT = 300;

watch(
  () => props.modelValue,
  (val) => {
    dialogVisible.value = val;
  }
);

watch(
  () => props.imgFile,
  (file) => {
    if (file) {
      const reader = new FileReader();
      reader.onload = (e) => {
        imgSrc.value = e.target.result;
        initCropper();
      };
      reader.readAsDataURL(file);
    }
  }
);

const initCropper = () => {
  if (cropper.value) {
    cropper.value.destroy();
  }

  nextTick(() => {
    cropper.value = new Cropper(imageRef.value, {
      aspectRatio: ASPECT_RATIO,
      viewMode: 1,
      autoCropArea: 0.8,
      responsive: true,
      cropBoxResizable: false,
      cropBoxMovable: true,
      toggleDragModeOnDblclick: false,
      ready() {
        // 设置固定裁剪尺寸
        this.cropper.setCropBoxData({
          width: CROP_WIDTH,
          height: CROP_HEIGHT,
        });
      },
      crop(event) {
        // 实时更新预览图片
        const canvas = cropper.value.getCroppedCanvas({
          width: CROP_WIDTH,
          height: CROP_HEIGHT,
        });
        previewSrc.value = canvas.toDataURL("image/jpeg", 0.9);
      },
    });
  });
};

const handleReset = () => {
  if (cropper.value) {
    cropper.value.reset();
  }
};

const handleConfirm = () => {
  if (cropper.value) {
    // 获取裁剪后的图片（base64格式）
    const croppedCanvas = cropper.value.getCroppedCanvas({
      width: CROP_WIDTH,
      height: CROP_HEIGHT,
      minWidth: 256,
      minHeight: 256,
      maxWidth: 4096,
      maxHeight: 4096,
      fillColor: "#fff",
      imageSmoothingEnabled: true,
      imageSmoothingQuality: "high",
    });

    // 转换为Blob对象
    croppedCanvas.toBlob(
      (blob) => {
        emit("cropped", blob);
        dialogVisible.value = false;
      },
      "image/jpeg",
      0.9
    ); // 90%质量

    handleClose();
  }
};

const handleClose = () => {
  if (cropper.value) {
    cropper.value.destroy();
  }
  emit("update:modelValue", false);
};

// 左转
const rotateLeft = () => {
  if (cropper.value) {
    cropper.value.rotate(-90); // 逆时针旋转90度
  }
};

// 右转
const rotateRight = () => {
  if (cropper.value) {
    cropper.value.rotate(90); // 顺时针旋转90度
  }
};
</script>

<style scoped>
.cropper-container {
  display: flex;
  justify-content: space-between;
  align-items: start;
  height: 500px;
}

.cropper-wrapper {
  width: 700px;
  height: 100%;
  overflow: hidden;
}

.cropper-wrapper img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.preview-container {
  display: flex;
  align-items: center;
  margin-right: 20px;
}

.preview-label {
  margin-right: 10px;
  font-weight: bold;
}

.preview-image {
  width: 200px;
  height: 200px;
  border: 1px solid #ddd;
  overflow: hidden;
  border-radius: 10px;
  overflow: hidden;
}

.preview-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cropper-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 20px;
  text-align: right;
}
</style>